using codeparser.net.Contracts;

using System;
using System.Collections.Generic;
using System.Text;

namespace codeparser.net
{
    /// <summary>
    /// Represents a tag.
    /// </summary>
    internal class Tag : IToken
    {
        /// <summary>
        /// Contains the tag name.
        /// </summary>
        private string _name;

        /// <summary>
        /// Contains the original string.
        /// </summary>
        private string _originalString;

        /// <summary>
        /// Contains whether this tag is a closing tag.
        /// </summary>
        private bool _isClosingTag;

        /// <summary>
        /// Contains the parameters.
        /// </summary>
        private List<TagParameter> _parameters;

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get
            {
                return this._name;
            }

            set
            {
                this._name = value;
            }
        }

        /// <summary>
        /// Gets or sets the original string.
        /// </summary>
        /// <value>The original string.</value>
        public string OriginalString
        {
            get
            {
                return this._originalString;
            }

            set
            {
                this._originalString = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is a closing tag.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is a closing tag; otherwise, <c>false</c>.
        /// </value>
        public bool IsClosingTag
        {
            get
            {
                return this._isClosingTag;
            }
        }

        /// <summary>
        /// Gets the parameters.
        /// </summary>
        /// <value>The parameters.</value>
        public List<TagParameter> Parameters
        {
            get
            {
                return this._parameters;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Tag"/> class.
        /// </summary>
        /// <param name="name">The name, eventually including a leading slash.</param>
        public Tag(string name)
        {
            // Set the original string.
            this._originalString = "[" + name + "]";

            // Check whether the tag is a closing tag.
            this._isClosingTag = name.StartsWith("/");

            // Cut off the leading slash if neccessary.
            name = name.TrimStart('/');

            // Check for parameters.
            int positionSpace = name.IndexOf(" ");
            int positionEqual = name.IndexOf("=");

            // If there is none of them, set the name and return.
            if (positionSpace == -1 && positionEqual == -1)
            {
                this._name = name;
                return;
            }

            // Eventually, only one of both has been found. To prevent C# to try to access position
            // -1, the max value is then used.
            positionSpace = positionSpace == -1 ? Int32.MaxValue : positionSpace;
            positionEqual = positionEqual == -1 ? Int32.MaxValue : positionEqual;

            // If there is a parameter, cut the name off.
            this._name = name.Substring(0, System.Math.Min(positionSpace, positionEqual));
            name = name.Substring(System.Math.Min(positionSpace, positionEqual) + 1);

            // Split the parameter string into a parameter array.
            string[] parameters = name.Split(' ');

            // Iterate over all parameters and get the keys and values.
            this._parameters = new List<TagParameter>();
            for (int i = 0; i < parameters.Length; i++)
            {
                // Check whether the first parameter is unnamed.
                if (i == 0 && (positionEqual < positionSpace))
                {
                    this._parameters.Add(new TagParameter("default", parameters[i]));
                    continue;
                }

                // Check all named parameters.
                int positionSeparator = parameters[i].IndexOf('=');

                // Add the parameter to the list of parameters.
                this._parameters.Add(new TagParameter(parameters[i].Substring(0, positionSeparator), parameters[i].Substring(positionSeparator + 1)));
            }
        }
    }
}